import Bb from 'backbone';
import Mn from 'backbone.marionette';
import FacadeModelApiMixin from '../../base/components/FacadeModelApiMixin.js';
import Radio from 'backbone.radio';
import {
    ajax_call
} from '../../tools.js';

import TotalModel from '../models/TotalModel.js';
import ExpenseCollection from '../models/ExpenseCollection.js';
import ExpenseKmCollection from '../models/ExpenseKmCollection.js';
import BookMarkCollection from '../models/BookMarkCollection.js';
import NodeFileCollection from "../../common/models/NodeFileCollection";
import StatusLogEntryCollection
from "../../common/models/StatusLogEntryCollection";

const FacadeClass = Mn.Object.extend(FacadeModelApiMixin).extend({
    radioEvents: {
        "changed:line": "computeLineTotal",
        "changed:kmline": "computeKmLineTotal",
        "attachment:saved": "onAttachmentSaved",
        "status:justified:changed": "onGlobalJustifiedChanged",
    },
    radioRequests: {
        'get:collection': 'getCollectionRequest',
        'get:model': 'getModelRequest',
        'get:totalmodel': 'getTotalModelRequest',
        'get:bookmarks': 'getBookMarks',
        'get:linkedFiles': 'getLinkedFiles',
        'get:file': 'getFile',
        'get:supplier': 'getSupplier',
        'has:expenseLines': 'hasExpenseLines',
        'create:return_expense_kmline': 'createReturnKmLine',
    },
    onGlobalJustifiedChanged(value) {
        this.collections.lines.each(
            l => (l.justified !== null) && l.set('justified', value)
        );
    },
    setup(options) {
        console.log("Facade.setup");
        console.table(options);
        this.url = options['context_url'];
        this.config = Radio.channel('config');
    },
    start() {
        console.log("Starting the facade");
        let deferred = ajax_call(this.url);
        return deferred.then(this.setupModels.bind(this));
    },
    setupModels(context_datas) {
        this.datas = context_datas;
        this.models = {};
        this.collections = {};
        this.totalmodel = new TotalModel();

        var lines = context_datas['lines'];
        this.collections['lines'] = new ExpenseCollection(lines);
        this.collections.status_history = new StatusLogEntryCollection(
            context_datas.status_history,
        );
        this.watchLinkToFiles();
        this.watchCollectionAggregateStatus();

        let attachments = context_datas['attachments'];
        this.collections['attachments'] = new NodeFileCollection(attachments);

        // FIXME
        let attachments_url = AppOption['file_upload_url'];
        this.collections['attachments'].url = attachments_url;

        var kmlines = context_datas['kmlines'];
        this.collections['kmlines'] = new ExpenseKmCollection(kmlines);

        const bookmarks = this.config.request('get:options', 'bookmarks');
        this.bookmarks = new BookMarkCollection(bookmarks);
        this.suppliers = new Bb.Collection(
            this.config.request('get:options', 'suppliers')
        );

        this.computeLineTotal();
        this.computeKmLineTotal();
    },
    watchCollectionAggregateStatus() {
        this.collections['lines'].on(
            'aggregate:change:justified',
            (function (newValue) {
                let channel = this.getChannel();
                channel.request('set:globalJustified', newValue);
            }).bind(this),
        );
    },
    watchLinkToFiles() {
        let lines = this.collections['lines'];
        lines.on('change:files', this.notifyLinkedFilesChanged.bind(this));
        lines.on(
            'add remove',
            function (model) {
                if (model.get('files').length > 0) {
                    this.notifyLinkedFilesChanged();
                }
            },
            this
        );
    },
    notifyLinkedFilesChanged() {
        this.getChannel().trigger('linkedFilesChanged');
    },
    getBookMarks() {
        return this.bookmarks;
    },
    hasExpenseLines() {
        return !this.collections['lines'].isEmpty();
    },
    getLinkedFiles() {
        return this.collections['lines'].collectLinkedFileIds();
    },
    getFile(id) {
        return this.collections['attachments'].get(id);
    },
    getSupplier(id) {
        return this.suppliers.findWhere(x => x.get('value') == id);
    },
    computeLineTotal() {
        /*
         * compute the line totals for the given category
         */
        const categories = ['1', '2'];

        var collection = this.collections['lines'];
        var datas = {}
        _.each(categories, function (category) {
            datas['ht_' + category] = collection.total_ht(category);
            datas['tva_' + category] = collection.total_tva(category);
            datas['ttc_' + category] = collection.total(category);
        });
        datas['ht'] = collection.total_ht();
        datas['tva'] = collection.total_tva();
        datas['ttc'] = collection.total();
        this.totalmodel.set(datas);
        var channel = this.getChannel();
        _.each(categories, function (category) {
            channel.trigger('change:lines_' + category);
        });
    },
    computeKmLineTotal() {
        /*
         * Compute the kmline totals for the given category
         */
        const categories = ['1', '2'];
        var collection = this.collections['kmlines'];
        var datas = {}
        _.each(categories, function (category) {
            datas['km_' + category] = collection.total_km(category);
            datas['km_ttc_' + category] = collection.total(category);
        });
        datas['km_tva'] = collection.total_tva();
        datas['km_ht'] = collection.total_ht();
        datas['km'] = collection.total_km();
        datas['km_ttc'] = collection.total();
        this.totalmodel.set(datas);

        var channel = this.getChannel();
        _.each(categories, function (category) {
            const eventName = 'change:kmlines_' + category
            console.log("Triggering %s", eventName)
            channel.trigger(eventName);
        });
    },
    createReturnKmLine(originalModel) {
        const collection = this.collections['kmlines'];
        const returnModel = originalModel.instantiateReturnLine();
        collection.add(returnModel);
        returnModel.save(this.changedAttributes, {wait: true, sync: true, patch: true});
    },
    getTotalModelRequest() {
        return this.totalmodel;
    },
    onAttachmentSaved(attachment) {
        this.collections['attachments'].add(attachment);
    },
});
const Facade = new FacadeClass();
export default Facade;
